package model.agent

//import java.time.Month;

import groovy.transform.TypeChecked
import model.Model


class HouseHold extends Agent {

	Firm workingFirm = null

	ArrayList<Firm> allFirms

	ArrayList<Firm> shoppingFirms = []

	def dailyCons
	float accCons

	def HouseHold(){
		[
			"money",
			"rWage",
			"pConsumption",
			"mRes"
		].each{ this.addProperty(it) }
	}

	def initMonth(){

		adjustPConsumption()

		searchForBetterPrice()

		searchForDemond()

		serachForJob()
	}

	def endMonth(){
		adjustRWage()
		mRes = pConsumption - accCons
	}

	def adjustRWage(){
		if(workingFirm != null){
			//有工作
			if(rWage < workingFirm.mWage){	//
				rWage = workingFirm.mWage
			}
		}else{
			//rWage *= 0.9
			rWage *= 0.1
		}

	}

	// 月度调整消费
	def adjustPConsumption() {
		accCons = 0

		def tc = money * Model.MPC / getAveragePrice()
		pConsumption = Math.min(tc ** Model.CONSUMPTION_FACTOR,tc)

		dailyCons = pConsumption / Model.DAYS_OF_MONTH

		//out "计划月消费:" + pConsumption
		//pConsumptionHis.add(pConsumption)
	}

	def shopping() {

		def order = (0..shoppingFirms.size()-1).toList()

		Model.shuffle(order)
		//out order

		def ac = 0 				//当日实际消费(量)
		def dc = dailyCons 		//当日剩余消费(量)

		order.each { int i ->
			//以一个随机的顺序
			if (dc > 0 && money>0){ // 当天还有消费需求
				Firm f = shoppingFirms[i]

				def out
				def value = dc * f.mPrice
				//				out dc
				//				out f.mPrice
				//				out value
				if (value <= money){ //买得起
					out = f.sell(dc)
				}else{ //买不起
					out = f.sell(money/f.mPrice)
				}
				//out out
				def aValue = out * f.mPrice
				dc -= out
				money -= aValue

				ac += out
			}
		} // 一天交易结束

		accCons += ac	//累积到月实际消费
		//		if(who ==1)out "实际消费: " + ac
		//		if(who ==1)out "剩余计划消费: " + pConsumption

	}

	private float getAveragePrice(){
		float sum = 0
		shoppingFirms.each { Firm f ->
			sum += (float)f.mPrice
		}
		return sum / shoppingFirms.size()
	}

	/**
	 * 随机选现有的typeA公司
	 * 以公司体积成正比的概率选择新的公司
	 * 如果新公司的价格低到一定程度，则断开原typeAlink，建立新的link
	 * @return
	 */
	def searchForBetterPrice(){
		if(Model.random() < Model.PRICE_SEARCH_RATE){
			changeOneShoppingFirms()
		}
	}

	def searchForDemond(){
		if(mRes>0 ){
			if(Model.random() < Model.DEMAND_SEARCH_RATE){
				changeOneShoppingFirms()
			}
		}
	}

	def changeOneShoppingFirms(){
		Firm fa = Model.oneof(shoppingFirms)	//选一个已经有的公司
		Firm fb = Model.oneof(allFirms - shoppingFirms)

		if ((fa.mPrice/fb.mPrice) >= (1 + Model.BETTER_PRICE_FACTOR)){
			shoppingFirms.remove(fa)
			shoppingFirms.add(fb)
		}
	}

	/**
	 * 1. 如果失业，则随机的顺序遍历所有公司，
	 * 找到一家有空缺，且工资满足保留工资的公司，建立typeBlink
	 * 2. 在职且工资满足，则已一定概率询问一家随机的公司
	 * 3. 在职且工资不满足，则以概率1询问一家随机的公司
	 * @return
	 */
	def serachForJob(){
		if (workingFirm == null) {	//失业
			def order = (0..allFirms.size()-1).toList()
			Model.shuffle(order)
			order.each{ int i ->
				if(workingFirm != null){return}
				Firm f = allFirms[i]
				out("${this}申请${f}")
				apply(f)
				
			}
		}else{
			Firm fa = workingFirm
			if(fa.mWage >= rWage){ 	//实际工资 >= 保留工资
				if (Model.random() < Model.HIGHER_WAGE_SEARCH_RATE){
					Firm fb = Model.oneof(allFirms - fa)
					out("${this}申请${fb}")
					apply(fb)
					
				}
			}else{					//实际工资 < 保留工资
				Firm fb = Model.oneof(allFirms - fa)
				out("${this}申请${fb}")
				apply(fb)
				
			}
		}

	}

	def apply(Firm fb){
		if(fb.applyFrom(this)){
			if(workingFirm != null){
				workingFirm.workers.remove(this)
			}
			workingFirm = fb
			out("${this}找到了新工作!${fb}")
		}
	}


	String toString(boolean detailed=false){
		def s = super.toString()
		if(detailed){
			s+="\n" + "working firm: " + workingFirm.toString()
			s+= "\n" + "shopping firms: " + shoppingFirms.toString()

		}
		return s
	}
}
